#include "tasks.h"

/*-----------------------------------------------------------------------------
 *  Declaração das variáveis definidas no header
 *-----------------------------------------------------------------------------*/

int mode;

buffer<string*> inputBuffer(2);
buffer<Tokens*> wordsBuffer(2);
buffer<Tokens*> phrasesBuffer(2);

Reader *reader;

Parser *wparser;
Parser *pparser;

PalindromeUtil *wputil;
PalindromeUtil *pputil;

ErathostenesSieve *sieve;

bool isWParserFinished;
bool isPParserFinished;
bool isWPalinsFinished;
bool isPPalinsFinished;

ulong length;

int rank, tasks;
ulong offset, size;

double readTime, parserTime, palinTime, primeTime;

/*
 * ===  FUNCTION  ======================================================================
 *         Name:  readFromInputFile
 *  Description:  Função que lê um bloco do arquivo de entrada
 * =====================================================================================
 */
void readFromInputFile(uint i)
{
    /* Se o parser de palavras e de frases terminou, não é preciso fazer nada */
    if(i < 0 || (isPParserFinished && isWParserFinished))
        return;

    Chronometer c;

    /* Lê um bloco e o coloca no buffer */
    string *block = reader->readBlock();
    inputBuffer.put(block, i);

    readTime += c.getMiliseconds();
}

/*
 * ===  FUNCTION  ======================================================================
 *         Name:  tokenizeBlock
 *  Description:  Função que divide o bloco em palavras e/ou frases
 * =====================================================================================
 */
void tokenizeBlock(uint i)
{
    /* Se o parser de palavras e de frases terminou, não é preciso fazer nada */
    if(i < 1 || (isPParserFinished && isWParserFinished))
        return;

    Chronometer c;

    /* Recupera o bloco do buffer */
    string *block = inputBuffer.get(i - 1);

    /* Se o parser de palavras ainda não terminou */
    if(!isWParserFinished)
    {
        /* Divide o bloco em palavras e as colocam no buffer */
        Tokens *words = wparser->getTokens(block);
        wordsBuffer.put(words, i - 1);

//        Parser::printTokens(ofs, words);
    }

    /* Se for modo texto menor e o parser de frases ainda não terminou */
    if(mode == SMALLER_TEXT && !isPParserFinished)
    {
        /* Divide o bloco em frases e as colocam no buffer */
        Tokens *phrases = pparser->getTokens(block);
        phrasesBuffer.put(phrases, i - 1);
    }

    /* Deleta o bloco */
    delete block;

    parserTime += c.getMiliseconds();
}

/*
 * ===  FUNCTION  ======================================================================
 *         Name:  checkForPalindromes
 *  Description:  Função que verifica se as palavras e/ou frases são palíndromas e de
 *                soma prima
 * =====================================================================================
 */
void checkForPalindromes(uint i)
{
    if(i < 2)
        return;

    Palindromes *wp = NULL;
    Chronometer c;

    /* Se o verificador de palavras ainda não terminou */
    if(!isWPalinsFinished)
    {
        /* Checa por palavras palíndromas */
        Tokens *words = wordsBuffer.get(i - 2);
        wp = wputil->checkForPalindromes(words);

        /* Deleta as palavras */
        Parser::deleteTokens(&words);
    }

    /* Se for modo texto menor e o verificador de frases ainda não terminou */
    if(mode == SMALLER_TEXT && !isPPalinsFinished)
    {
        /* Checa por frases palíndromas */
        Tokens *phrases = phrasesBuffer.get(i - 2);
        Palindromes *pp = pputil->checkForPalindromes(phrases);

        /* Deleta as frases */
        Parser::deleteTokens(&phrases);
        delete pp;
    }

    palinTime += c.getMiliseconds();
    c.reset();

    /* Se for o texto maior, verifica por primos */
    if(mode == BIGGER_TEXT)
    {
        uint sum = sieve->checkForPrimes(wp);
        wputil->incNPrimes(sum);
        delete wp;
    }

    /* Seta os flags de término dos verificadores */
    isWPalinsFinished = isWParserFinished;
    isPPalinsFinished = isPParserFinished;

    primeTime += c.getMiliseconds();
}
